package com.jigang.study.netty.handler.messagepack;

import com.jigang.study.netty.handler.common.UserInfo;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;

/**
 * todo 类注释
 *
 * @author wujigang
 * @date 2019/8/30
 */
public class MsgpackEchoClient {

    private String host;

    private int port;

    private int sendNumber;

    public MsgpackEchoClient(String host, int port, int sendNumber) {
        this.host = host;
        this.port = port;
        this.sendNumber = sendNumber;
    }

    public void run() throws InterruptedException {

        EventLoopGroup group = new NioEventLoopGroup();

        try {

            Bootstrap b = new Bootstrap();

            b.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
//                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {

//                            ch.pipeline().addLast("msg decoder", new MsgpackDecoder())
//                                    .addLast("msg encoder", new MsgpackEncoder())
//                                    .addLast(new MsgpackEchoClientHandler(sendNumber));
                            // 解决粘包问题
                            ch.pipeline().addLast("frameDecoder",new LengthFieldBasedFrameDecoder(65535, 0, 2,0,2));
                            ch.pipeline().addLast("msgpack decoder", new MsgpackDecoder());
                            // 解决粘包问题
                            ch.pipeline().addLast("frameEncoder",new LengthFieldPrepender(2));
                            ch.pipeline().addLast("msgpack encoder", new MsgpackEncoder());
                            ch.pipeline().addLast(new MsgpackEchoClientHandler(sendNumber));

                        }
                    });

            ChannelFuture f = b.connect(host, port).sync();

            f.channel().closeFuture().sync();

        } finally {
            group.shutdownGracefully();
        }
    }

    private static class MsgpackEchoClientHandler extends ChannelHandlerAdapter {

        private int senderNumber;

        public MsgpackEchoClientHandler(int senderNumber) {
            this.senderNumber = senderNumber;
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) {

            UserInfo[] infos = getUserInfo();

            for (UserInfo info : infos) {
                ctx.writeAndFlush(info);
            }

            ctx.flush();
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            System.out.println("Client receive the msgpack message : " + msg);
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) {
            ctx.flush();
        }

        private UserInfo[] getUserInfo() {

            UserInfo[] infos = new UserInfo[senderNumber];

            for (int i = 0; i < senderNumber; i++) {
                UserInfo info = new UserInfo();

                info.setAge(10 + i);
                info.setName("Name" + i);

                infos[i] = info;
            }

            return infos;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new MsgpackEchoClient("localhost", 8080, 16).run();
    }
}
